#include "include/rpc_helper.h"
#include "include/rpc_def.h"
#include "base/fast_hash.h"

#include <google/protobuf/message.h>
#include <google/protobuf/service.h>
#include <google/protobuf/descriptor.h>

namespace rpc {

HandlerMap::~HandlerMap() {
  for (std::map<uint32, Handler*>::iterator it = handler_map_.begin();
      it != handler_map_.end(); ++it) {
    Handler* handler = it->second;
    delete handler->request;
    delete handler->response;
    delete handler;
  }

  handler_map_.clear();
}

void HandlerMap::AddService(Service* service) {
  CHECK(service != NULL);

  const ServiceDescriptor* sdesc = service->GetDescriptor();
  for (int32 i = 0; i < sdesc->method_count(); ++i) {
    const MethodDescriptor* mdesc = sdesc->method(i);
    uint32 fid = GetFunidByMethodDescriptor(mdesc);
    CHECK(fid != (uint32) INVALIED_FUNC_ID);

    Handler* handler = new Handler;
    handler->service = service;
    handler->method_descriptor = mdesc;
    handler->request = service->GetRequestPrototype(mdesc).New();
    handler->response = service->GetResponsePrototype(mdesc).New();

    CHECK(handler_map_.insert(std::make_pair(fid, handler)).second);
  }
}

uint32 HandlerMap::GetFunidByMethodDescriptor(const MethodDescriptor* mdesc) {
  if (mdesc == NULL) {
    return (uint32) INVALIED_FUNC_ID;
  }

  std::string mname = mdesc->full_name();
  return FastHash32(mname.c_str(), mname.size());
}
}
